#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f3f3f3f3f
typedef long long ll;
const int N = 2e5 + 10;

int n, k;
ll a[N];
vector<int> G[N];
vector<vector<vector<ll>>> dp(n + 1,
                              vector<vector<ll>>(7, vector<ll>(2, -INF)));
// dp[u][j][0]:考虑以u为根的子树，不算点u，选取恰好j条互不重叠的路径，权值总和的最大值
// dp[u][j][1]:考虑以u为根的子树，算点u，选取恰好j条互不重叠的路径，权值总和的最大值
vector<vector<ll>> f(n + 1, vector<ll>(7, -INF));
// f[u][j]：考虑以u为根的子树，选取恰好j条互不重叠的路径，其中必须存在一条路径以u为端点，权值总和的最大值

void DFS(int u, int father) {
  // init
  dp[u][0][0] = 0;
  dp[u][0][1] = 0;
  dp[u][1][1] = a[u];
  f[u][1] = a[u];
  for (auto v : G[u]) {
    if (v == father) continue;
    DFS(v, u);
    // ！注意，在进行树形dp时，若想使用合并子树之前的结果转移，则最好（bixu）先将转移之前的结果保存下来，以避免在转移过程中被覆盖
    auto pre_dp_u = dp[u];
    auto pre_f_u = f[u];

    /*
    状态转移：
当合并子树时，需要考虑多种情况：
不选当前子树的路径
选当前子树的路径并与父节点连接
选当前子树的路径但不与父节点连接
通过双重循环枚举路径数量的分配方式
    */
    for (int j = 1; j <= k; j++) {
      for (int j1 = 0; j1 <= j; j1++) {
        int j2 = j - j1;
        max(dp[u][j][1], pre_dp_u[j1][1] + dp[v][j2][1]);
        max(dp[u][j][1], pre_f_u[j1] + f[v][j2 + 1]);
        max(f[u][j], pre_f_u[j1] + dp[v][j2][1]);
        max(f[u][j], (f[v][j1] + a[u]) + pre_dp_u[j2][0]);
        max(dp[u][j][0], pre_dp_u[j1][0] + dp[v][j2][1]);
      }
    }
  }
  // for(int j = 0; j <= k; j ++){
  //     printf("dp[%d][%d][%d] = %lld\n", u, j, 0, dp[u][j][0]);
  //     printf("dp[%d][%d][%d] = %lld\n", u, j, 1, dp[u][j][1]);
  // }
};
signed main() {
  cin >> n >> k;
  for (int i = 1; i <= n; i++) {
    cin >> a[i];
  }
  for (int i = 1; i <= n - 1; i++) {
    int u, v;
    cin >> u >> v;
    G[u].push_back(v);
    G[v].push_back(u);
  }

  DFS(1, 0);

  ll ans = 0;
  for (int i = 0; i <= k; i++) {
    ans = max(ans, dp[1][i][1]);
  }
  cout << ans << endl;
  return 0;
}